package com.back.service.impl;

import cn.hutool.core.lang.hash.Hash;
import com.back.excepction.BaseException;
import com.back.mapper.AnswerRecordsMapper;
import com.back.mapper.ExamRecordsMapper;
import com.back.mapper.ExamsMapper;
import com.back.model.dto.DoAnswerDTO;
import com.back.model.dto.SubmitQuestionDTO;
import com.back.model.dto.UserAnswerDTO;
import com.back.model.dto.taskInfo.TaskInfoQueryDTO;
import com.back.model.entity.AnswerRecords;
import com.back.model.entity.ExamRecords;
import com.back.model.entity.Exams;
import com.back.model.reslut.PageData;
import com.back.model.reslut.Result;
import com.back.model.vo.QuestionOptionsVO;
import com.back.model.vo.QuestionsVo;
import com.back.model.vo.TaskInfoVO;
import com.back.service.ExamRecordsService;
import com.back.service.ScoreService;
import com.back.utils.JacksonUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.back.model.entity.Questions;
import com.back.service.QuestionsService;
import com.back.mapper.QuestionsMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.common.collect.HashBiMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jspecify.annotations.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @description 针对表【questions(题目表)】的数据库操作Service实现
 * @createDate 2025-08-21 16:57:24
 */
@Service
@Slf4j
public class QuestionsServiceImpl extends ServiceImpl<QuestionsMapper, Questions>
        implements QuestionsService {

    @Resource
    private QuestionsMapper questionsMapper;

    @Resource
    private ExamRecordsService examRecordsService;
    @Resource
    private AnswerRecordsService answerRecordsService;

    @Resource
    private ScoreService scoreService;

    @Resource
    private ExamsMapper examsMapper;

    @Resource
    private TransactionTemplate transactionTemplate;


    @Transactional
    @Override
    public List<QuestionsVo> getQuestionList(DoAnswerDTO doAnswerDTO) {

        List<QuestionsVo> questionsDb = questionsMapper.getQuestionContentDTO(doAnswerDTO.getQueryId());
        log.info("随机之前: {}", JacksonUtils.objectToJson(questionsDb));

        // 随机用户题目选项  并映射结果（返回给用户题目的选项 和原来选项进行映射）
        List<QuestionsVo> questionsRandom = generateRandomizedTexts(doAnswerDTO.getUserId(), questionsDb);
        log.info("随机之后: {}", JacksonUtils.objectToJson(questionsRandom));
        // 保存做题记录（当题目但会给前端 就保存基本信息）
        /*   transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    saveRecoreds(doAnswerDTO,questionsRandom);
                }catch (Exception e){
                    log.error("保存过程中发生异常，事务已回滚", e);
                    // 2. 【关键】设置事务状态为回滚
                    status.setRollbackOnly();
                    // 3. 可以选择抛出一个新的运行时异常，让上层也知道失败了
                    throw new BaseException("业务保存失败");
                }

            }
        }); */
        Long examRecordId = examRecordsService.saveRecoreds(doAnswerDTO, questionsRandom);
        //屏蔽答案
        List<QuestionsVo> questionsRes = blockAnswer(questionsDb);
        for (QuestionsVo questionsVo : questionsRes) {
            questionsVo.setExamRecordId(examRecordId);
        }
        log.info("脱敏之后: {}", JacksonUtils.objectToJson(questionsRes));
        return questionsRes;

    }

    //提交题目
    @Override
    @Transactional
    public Result<BigDecimal> submitQuestion(SubmitQuestionDTO submitQuestionDTO) {
        LambdaQueryWrapper<AnswerRecords> queryWrapper = new QueryWrapper<AnswerRecords>().lambda();
        AnswerRecords answerRecords = answerRecordsService.getOne(queryWrapper.eq(AnswerRecords::getExamRecordId,
                submitQuestionDTO.getExamsRecordId()));

        List<UserAnswerDTO> userAnswerDTOList = submitQuestionDTO.getUserAnswerDTOList();
        String questionContext = answerRecords.getQuestioncontext();
        List<QuestionsVo> questionsVos = JacksonUtils.jsonToList(questionContext, QuestionsVo.class);

        //判题
        BigDecimal divide = scoreService.doScore(questionsVos, userAnswerDTOList);


        //保存结果
        examRecordsService.updateRecoreds(divide,submitQuestionDTO,questionsVos);

        Result<BigDecimal> result = new Result();
        result.setCode(0);
        result.setMsg("提交成功");
        result.setData(divide);
        return result;


    }





    private List<QuestionsVo> generateRandomizedTexts(Long userId, List<QuestionsVo> questionsVoList) {

        Map<Integer, HashBiMap<@Nullable Object, @Nullable Object>> ListReslut = new HashMap<>();

        List<QuestionsVo> questionsVoListTemp = questionsVoList.stream()
                .map(QuestionsVo::new) // 使用复制构造方法
                .collect(Collectors.toList());

        Map<Integer, QuestionsVo> questionMap = questionsVoListTemp.stream()
                .collect(Collectors.toMap(
                        QuestionsVo::getId,  // key: id
                        question -> question, // value: 对象本身
                        (existing, replacement) -> existing // 处理重复key的冲突解决策略
                ));

        for (QuestionsVo questionsVo : questionsVoList) {
            List<QuestionOptionsVO> questionOptions = questionsVo.getQuestionOptions();
            List<String> originalTexts = questionOptions.stream()
                    .map(QuestionOptionsVO::getOptionText)
                    .collect(Collectors.toList());

            if (StringUtils.isNotEmpty(questionsVo.getCorrectAnswers())) {
                questionsVo.setMultipleAnswers(JacksonUtils.jsonToList(questionsVo.getCorrectAnswers(), String.class));
            }
            // 使用确定的随机算法
            long randomSeed = userId.hashCode();
            //随机后-选项和结果映射关系
            Map<String, String> questionOptionsBiMap = new HashMap<>();

            //随机选项 和原来选项映射关系
            HashBiMap<@Nullable Object, @Nullable Object> capitalCountryBiMap = HashBiMap.create();

            List<String> shuffledTexts = new ArrayList<>(originalTexts);
            Collections.shuffle(shuffledTexts, new Random(randomSeed));
            for (int i = 0; i < questionOptions.size(); i++) {
                questionOptions.get(i).setOptionText(shuffledTexts.get(i));
                questionOptionsBiMap.put(questionOptions.get(i).getOptionText(), questionOptions.get(i).getOptionId());
            }

            QuestionsVo questionsVoTemp = questionMap.get(questionsVo.getId());
            List<QuestionOptionsVO> questionOptionsTemp = questionsVoTemp.getQuestionOptions();
            //遍历随机之前的选项结果
            for (QuestionOptionsVO questionOptionsVOTemp : questionOptionsTemp) {
                String option = (String) questionOptionsBiMap.get(questionOptionsVOTemp.getOptionText());
                capitalCountryBiMap.put(option, questionOptionsVOTemp.getOptionId());
            }
            ListReslut.put(questionsVo.getId(), capitalCountryBiMap);
        }


        //修改题目的答题为 随机后的
        for (QuestionsVo questionsVo : questionsVoList) {
            //单选
            HashBiMap<@Nullable Object, @Nullable Object> objectObjectHashBiMap = ListReslut.get(questionsVo.getId());
            //单选
            if (0 == questionsVo.getType()) {
                String option = (String) objectObjectHashBiMap.inverse().get(questionsVo.getCorrectAnswer());
                questionsVo.setCorrectAnswer(option);
                //多选
            } else if (1 == questionsVo.getType()) {
                List<String> multipleAnswersNew = new ArrayList<>();
                for (String multipleAnswers : questionsVo.getMultipleAnswers()) {
                    String option = (String) objectObjectHashBiMap.inverse().get(multipleAnswers);
                    multipleAnswersNew.add(option);
                }
                questionsVo.setMultipleAnswers(multipleAnswersNew);
            }

        }

        return questionsVoList;

    }


    private List<QuestionsVo> blockAnswer(List<QuestionsVo> questions) {
        for (QuestionsVo questionsVo : questions) {
            questionsVo.setCorrectAnswer(null);
            questionsVo.setCorrectAnswers(null);
            questionsVo.setMultipleAnswers(null);
        }
        return questions;
    }

}




